home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / vm / vmPrefetch.c < prev    next >
C/C++ Source or Header  |  1991-06-27  |  7KB  |  270 lines

  1. /* 
  2.  * vmPrefetch.c --
  3.  *
  4.  *      This file contains routines to do prefetch.
  5.  *    
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/vm/RCS/vmPrefetch.c,v 9.3 90/09/12 13:36:36 shirriff Exp Locker: mgbaker $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14. #include <sprite.h>
  15. #include <vmStat.h>
  16. #include <vm.h>
  17. #include <vmInt.h>
  18. #include <user/vm.h>
  19. #include <sync.h>
  20. #include <dbg.h>
  21. #include <list.h>
  22. #include <lock.h>
  23. #include <sys.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26.  
  27. Boolean    vmPrefetch = FALSE;
  28.  
  29. /*
  30.  * Information needed to do a prefetch.
  31.  */
  32. typedef struct {
  33.     Vm_VirtAddr    virtAddr;
  34. } PrefetchInfo;
  35.  
  36. static Boolean StartPrefetch _ARGS_((register Vm_Segment *segPtr,
  37.     register Vm_PTE *ptePtr));
  38. static void DoPrefetch _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  39. static void FinishPrefetch _ARGS_((Vm_VirtAddr *virtAddrPtr,
  40.     register Vm_PTE *ptePtr));
  41. static void AbortPrefetch _ARGS_((Vm_VirtAddr *virtAddrPtr, Vm_PTE *ptePtr));
  42.  
  43.  
  44. /*
  45.  * ----------------------------------------------------------------------------
  46.  *
  47.  * VmPrefetch --
  48.  *
  49.  *    Start a fetch for the next page if it isn't resident and it's on
  50.  *    swap or in a file.
  51.  *
  52.  * Results:
  53.  *    None.
  54.  *
  55.  * Side effects:
  56.  *    Memory is allocated.
  57.  *
  58.  * ----------------------------------------------------------------------------
  59.  */
  60. void
  61. VmPrefetch(virtAddrPtr, ptePtr)
  62.     register    Vm_VirtAddr    *virtAddrPtr;
  63.     register    Vm_PTE        *ptePtr;
  64. {
  65.     register    PrefetchInfo    *prefetchInfoPtr;
  66.     register    Vm_Segment    *segPtr;
  67.  
  68.     segPtr = virtAddrPtr->segPtr;
  69.     if (segPtr->type == VM_STACK) {
  70.     if (virtAddrPtr->page == mach_LastUserStackPage) {
  71.         return;
  72.     }
  73.     } else {
  74.     if (virtAddrPtr->page == segOffset(virtAddrPtr) + segPtr->numPages - 1) {
  75.         return;
  76.     }
  77.     }
  78.     if (!(*ptePtr & VM_VIRT_RES_BIT) || 
  79.         (*ptePtr & (VM_ZERO_FILL_BIT | VM_PHYS_RES_BIT | VM_IN_PROGRESS_BIT | 
  80.             VM_COR_BIT | VM_COW_BIT)) || 
  81.      !StartPrefetch(segPtr, ptePtr)) {
  82.     return;
  83.     }
  84.     prefetchInfoPtr = (PrefetchInfo *)malloc(sizeof(PrefetchInfo));
  85.     prefetchInfoPtr->virtAddr.segPtr = segPtr;
  86.     prefetchInfoPtr->virtAddr.page = virtAddrPtr->page + 1;
  87.     prefetchInfoPtr->virtAddr.flags = 0;
  88.     prefetchInfoPtr->virtAddr.sharedPtr = virtAddrPtr->sharedPtr;
  89.     switch (segPtr->type) {
  90.     case VM_CODE:
  91.         vmStat.codePrefetches++;
  92.         break;
  93.     case VM_HEAP:
  94.         if (*ptePtr & VM_ON_SWAP_BIT) {
  95.         vmStat.heapSwapPrefetches++;
  96.         } else {
  97.         vmStat.heapFSPrefetches++;
  98.         }
  99.         break;
  100.     case VM_STACK:
  101.         vmStat.stackPrefetches++;
  102.         break;
  103.     }
  104.     Proc_CallFunc(DoPrefetch, (ClientData)prefetchInfoPtr, 0);
  105. }
  106.  
  107.  
  108. /*
  109.  * ----------------------------------------------------------------------------
  110.  *
  111.  * StartPrefetch
  112.  *
  113.  *    Set up things for the next page to be fetched.
  114.  *
  115.  * Results:
  116.  *    TRUE if decided that the next page should be prefetched.
  117.  *
  118.  * Side effects:
  119.  *    In progress bit set in the pte if a prefetch should be done.
  120.  *
  121.  * ----------------------------------------------------------------------------
  122.  */
  123. ENTRY static Boolean
  124. StartPrefetch(segPtr, ptePtr)
  125.     register    Vm_Segment    *segPtr;
  126.     register    Vm_PTE        *ptePtr;
  127. {
  128.     LOCK_MONITOR;
  129.  
  130.     if (*ptePtr & (VM_ZERO_FILL_BIT | VM_PHYS_RES_BIT | 
  131.                 VM_IN_PROGRESS_BIT | VM_COR_BIT | VM_COW_BIT)) {
  132.     UNLOCK_MONITOR;
  133.     return(FALSE);
  134.     }
  135.     *ptePtr |= VM_IN_PROGRESS_BIT;
  136.     segPtr->ptUserCount++;
  137.  
  138.     UNLOCK_MONITOR;
  139.     return(TRUE);
  140. }
  141.  
  142.  
  143. /*
  144.  * ----------------------------------------------------------------------------
  145.  *
  146.  * DoPrefetch --
  147.  *
  148.  *    Fetch the given page for the segment.
  149.  *
  150.  * Results:
  151.  *    None.
  152.  *
  153.  * Side effects:
  154.  *    None.
  155.  *
  156.  * ----------------------------------------------------------------------------
  157.  */
  158. /*ARGSUSED*/
  159. static void
  160. DoPrefetch(data, callInfoPtr)
  161.     ClientData        data;
  162.     Proc_CallInfo    *callInfoPtr;
  163. {
  164.     register    PrefetchInfo    *prefetchInfoPtr;
  165.     unsigned    int        virtFrameNum;
  166.     register    Vm_PTE        *ptePtr;
  167.     ReturnStatus        status;
  168.  
  169.     prefetchInfoPtr = (PrefetchInfo *)data;
  170.     ptePtr = VmGetAddrPTEPtr(&(prefetchInfoPtr->virtAddr), 
  171.              prefetchInfoPtr->virtAddr.page);
  172.     /*
  173.      * Fetch a page frame.  Note that we don't block if no memory is
  174.      * available because we are a process out of the call-func process pool.
  175.      * If we block then we can easily use up all of the processes and there
  176.      * will be noone left to clean memory.  Thus it could cause deadlock.
  177.      */
  178.     virtFrameNum = VmPageAllocate(&prefetchInfoPtr->virtAddr, 
  179.                   VM_ABORT_WHEN_DIRTY);
  180.     if (virtFrameNum == VM_NO_MEM_VAL) {
  181.     vmStat.prefetchAborts++;
  182.     AbortPrefetch(&prefetchInfoPtr->virtAddr, ptePtr);
  183.     goto exit;
  184.     }
  185.     *ptePtr |= virtFrameNum;
  186.     if (*ptePtr & VM_ON_SWAP_BIT ||
  187.         prefetchInfoPtr->virtAddr.segPtr->type == VM_SHARED) {
  188.     vmStat.psFilled++;
  189.     if ( prefetchInfoPtr->virtAddr.segPtr->type == VM_SHARED) {
  190.         printf("Prefetching shared page\n");
  191.         }
  192.     status = VmPageServerRead(&prefetchInfoPtr->virtAddr, virtFrameNum);
  193.     } else {
  194.     vmStat.fsFilled++;
  195.     status = VmFileServerRead(&prefetchInfoPtr->virtAddr, virtFrameNum);
  196.     }
  197.     FinishPrefetch(&prefetchInfoPtr->virtAddr, ptePtr);
  198.     if (status != SUCCESS) {
  199.     VmKillSharers(prefetchInfoPtr->virtAddr.segPtr);
  200.     }
  201. exit:
  202.     VmDecPTUserCount(prefetchInfoPtr->virtAddr.segPtr);
  203.     free((Address)data);
  204. }
  205.  
  206.  
  207. /*
  208.  * ----------------------------------------------------------------------------
  209.  *
  210.  * FinishPrefetch --
  211.  *
  212.  *    Finish up a prefetch,
  213.  *
  214.  * Results:
  215.  *    None.
  216.  *
  217.  * Side effects:
  218.  *    None.
  219.  *
  220.  * ----------------------------------------------------------------------------
  221.  */
  222. ENTRY static void
  223. FinishPrefetch(virtAddrPtr, ptePtr)
  224.     Vm_VirtAddr        *virtAddrPtr;
  225.     register    Vm_PTE    *ptePtr;
  226. {
  227.     register    Vm_Segment    *segPtr;
  228.  
  229.     LOCK_MONITOR;
  230.  
  231.     segPtr = virtAddrPtr->segPtr;
  232.     segPtr->resPages++;
  233.     *ptePtr |= VM_PHYS_RES_BIT | VM_PREFETCH_BIT;
  234.     *ptePtr &= ~VM_IN_PROGRESS_BIT;
  235.     Sync_Broadcast(&segPtr->condition);
  236.     VmUnlockPageInt(Vm_GetPageFrame(*ptePtr));
  237.  
  238.     UNLOCK_MONITOR;
  239. }
  240.  
  241.  
  242. /*
  243.  * ----------------------------------------------------------------------------
  244.  *
  245.  * AbortPrefetch --
  246.  *
  247.  *    Clear the in progress bit from the page table entry.
  248.  *
  249.  * Results:
  250.  *    None.
  251.  *
  252.  * Side effects:
  253.  *    None.
  254.  *
  255.  * ----------------------------------------------------------------------------
  256.  */
  257. ENTRY static void
  258. AbortPrefetch(virtAddrPtr, ptePtr)
  259.     Vm_VirtAddr    *virtAddrPtr;
  260.     Vm_PTE    *ptePtr;
  261. {
  262.     LOCK_MONITOR;
  263.  
  264.     *ptePtr &= ~VM_IN_PROGRESS_BIT;
  265.     Sync_Broadcast(&virtAddrPtr->segPtr->condition);
  266.  
  267.     UNLOCK_MONITOR;
  268. }
  269.  
  270.